package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect     //定义切面类
public class AutoFillAspect {

    //前置通知--处理公共字段自动填充
    @Before("@annotation(com.sky.annotation.AutoFill)")
    public void autoFill(JoinPoint joinPoint) throws Exception {
        //1. 通过连接点获取到方法签名，根据方法签名获取方法对象
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod(); //方法对象
        String methodName = signature.getName();    //方法名字--insert
        System.out.println("methodName = "+methodName);

        //2. 通过连接点获取到方法参数
        Object[] args = joinPoint.getArgs();
        Object entity = null;
        if (args != null || args.length > 0) {
            entity = args[0];
        }

        //3.判断方法的操作类型
        AutoFill annotation = method.getAnnotation(AutoFill.class);
        OperationType value = annotation.value();
        if (value.equals(OperationType.INSERT)) {
            //如果是新增，那么赋值四个字段（创建时间、更新时间、创建人、更新人）
            //反射第一步：获取字节码对象；再根据字节码对象获取到方法对象，再调用方法对象赋值
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class)
                    .invoke(entity, LocalDateTime.now());
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class)
                    .invoke(entity, LocalDateTime.now());
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class)
                    .invoke(entity, BaseContext.getCurrentId());
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class)
                    .invoke(entity, BaseContext.getCurrentId());
        } else if (value.equals(OperationType.UPDATE)) {
            //如果是更新，那么赋值两个字段（更新时间、更新人）
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class)
                    .invoke(entity, LocalDateTime.now());
            entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class)
                    .invoke(entity, BaseContext.getCurrentId());
        }
    }
}
